package com.poetize.plus.utils;

import com.poetize.plus.properties.SecurityProperties;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.JwsHeader;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.UUID;

/**
 * @author zuosy
 * @created 2024/3/28 15:41
 */
@Component
@RequiredArgsConstructor
public class JwtUtil {

    private final SecurityProperties securityProperties;

    /**
     * 生成访问令牌
     *
     * @param username 用户名
     * @return 访问令牌
     */
    public String genAccessToken(String username) {
        // 生成令牌ID
        String uuid = UUID.randomUUID().toString();
        //签发时间
        Date now = new Date();
        // 过期时间
        Date expireDate = Date.from(now.toInstant().plus(
                securityProperties.getJwt().getExpire(),
                securityProperties.getJwt().getChronoUnit())
        );
        return buildJwt(username, uuid, now, expireDate);
    }


    /**
     * 生成访问令牌
     *
     * @param username 用户名
     * @return 访问令牌
     */
    public String genRefreshToken(String username) {
        // 生成令牌ID
        String uuid = UUID.randomUUID().toString();
        //签发时间
        Date now = new Date();
        // 过期时间
        Date expireDate = Date.from(now.toInstant().plus(
                securityProperties.getJwt().getRefreshExpiration(),
                securityProperties.getJwt().getChronoUnit())
        );

        return buildJwt(username, uuid, now, expireDate);
    }

    private String buildJwt(String username, String uuid, Date now, Date expireDate) {
        return Jwts.builder()
                // 设置头部信息
                .header()
                .add("typ", "JWT")
                .add("alg", securityProperties.getJwt().getAlgorithm().toString())
                .and()
                // 设置自定义负载信息
                .claim("username", username)
                .id(uuid) // 令牌ID
                .expiration(expireDate) // 过期日期
                .issuedAt(now) // 签发时间
                .subject(securityProperties.getJwt().getSubject())
                .issuer(securityProperties.getJwt().getIssuer()) // 签发者
                .signWith(Keys.hmacShaKeyFor(securityProperties.getJwt().getSecret().getBytes(StandardCharsets.UTF_8)),
                        securityProperties.getJwt().getAlgorithm().getType()) // 签名
                .compact();
    }



    /**
     * 获取payload中的用户信息
     *
     * @param token JWT Token
     * @return 用户信息
     */
    public String getUserFromToken(String token) {
        String user = "";
        Claims claims = parseClaims(token);
        if (claims != null) {
            user = (String) claims.get("username");
        }
        return user;
    }

    /**
     * 获取JWT令牌的过期时间
     *
     * @param token JWT令牌
     * @return 过期时间的毫秒级时间戳
     */
    public long getExpirationTime(String token) {

        Claims claims = parseClaims(token);
        if (claims != null) {
            return claims.getExpiration().getTime();
        }
        return 0L;
    }
    /**
     * 解析token
     *
     * @param token token
     * @return Jws<Claims>
     */
    public Jws<Claims> parseClaim(String token) {
        return Jwts.parser()
                .verifyWith(Keys.hmacShaKeyFor(securityProperties.getJwt().getSecret().getBytes(StandardCharsets.UTF_8)))
                .build()
                .parseSignedClaims(token);
    }

    /**
     * 解析token的头部信息
     *
     * @param token token
     * @return token的头部信息
     */
    public JwsHeader parseHeader(String token) {
        return parseClaim(token).getHeader();
    }

    /**
     * 解析token的载荷信息
     *
     * @param token token
     * @return token的载荷信息
     */
    public Claims parsePayload(String token) {
        return parseClaim(token).getPayload();
    }


    /**
     * 解析JWT Token中的Claims
     *
     * @param token JWT Token
     * @return Claims
     */
    public Claims parseClaims(String token) {
        try {
            return Jwts.parser()
                    .verifyWith(Keys.hmacShaKeyFor(securityProperties.getJwt().getSecret().getBytes(StandardCharsets.UTF_8)))
                    .build()
                    .parseSignedClaims(token)
                    .getPayload();
        } catch (Exception e) {
            return null;
        }
    }


}
